package com.rgbgame.physics;

import java.util.ArrayList;

import org.jbox2d.dynamics.Body;

/**
 * <p>
 * Superclass for userdata that lives on a Body.
 * Note that while often this will be unique per-body,
 * that is not necessary.  Often it will make more sense
 * to associate a single Actor with a collection of bodies,
 * such as when using a ragdoll.
 * </p>
 * <p>
 * See also ShapeData for the per-shape userdata superclass.
 * 
 * @author eric
 */
public class Actor {
	/** Group membership is done by flags on an int, hence max group # is 32. */
	static final public int MAX_GROUPS = 32;
	/** Total count of actors, used to generate unique ids */
	static private int idCount = 0;
	/** Unique id */
	protected int m_id;
	/** Type */
	protected ActorType m_type = ActorType.UNDEFINED;
	/** 
	 * Group membership flags - used in ContactEventDispatcher
	 */
	protected int m_groupFlags = 0;
	
	protected ArrayList<Body> m_bodies;
	
	public Actor() {
		m_id = idCount++;
		m_bodies = new ArrayList<Body>();
	}
	
	public ActorType getType() {
		return m_type;
	}
	
	public int getGroupFlags() {
		return m_groupFlags;
	}
	
	public void setGroupFlags(int groupFlags) {
		m_groupFlags = groupFlags;
	}
	
	public boolean isInGroup(int groupNum) {
		int toCheck = 1<<groupNum;
		return (m_groupFlags & toCheck) == toCheck;
	}
	
	public void addToGroup(int groupNum) {
		assert(groupNum < MAX_GROUPS);
		int tmp = 1<<groupNum;
		m_groupFlags |= tmp;
	}
	
	public void removeFromGroup(int groupNum) {
		assert(groupNum < MAX_GROUPS);
		int tmp = 1<<groupNum;
		m_groupFlags &= ~tmp;
	}
	
	public int getID() {
		return m_id;
	}
	
	public ArrayList<Body> getBodies() {
		return m_bodies;
	}
	
	/**
	 * Returns true if collisions should occur between the two
	 * actors.
	 * <BR><BR>
	 * <em>Warning</em>: This should be symmetrically defined, because
	 * JBox2d does not guarantee whether it will be called as
	 * this.shouldCollide(a) or a.shouldCollide(this) - if any
	 * asymmetry exists, it may cause bugs!
	 * @param a The actor to decide whether to check collisions against
	 * @return True if the collision should be processed
	 */
	public boolean shouldCollide(Actor a) {
		return true;
	}
	
	static public void resetStatics() {
		idCount = 0;
	}
}
